#ifndef LIST_H
#define LIST_H

typedef void * list_t;

/***** CORE APIS *******/

list_t list_alloc(void);                     /* allocate a new list */

/* list_free -- frees the list but doesn't free the client's memory */
void list_free(list_t list);

void list_insert_front(list_t list, void * record);
void list_insert_end(list_t list, void * record);

void * list_delete_front(list_t list);
void * list_delete_end(list_t list);

void list_delete_elem(list_t elem);

/* copies the records of list2 at the end of list1 and deallocates list2 */
void list_join(list_t list1, list_t list2);

int list_count(list_t list);                 /* slow!! */
int list_is_empty(list_t list);

/* Iteration APIS */
list_t list_next(list_t list);
list_t list_prev(list_t list);
void * list_item(list_t list);

/***** SUGAR APIS ********/

/* returns NULL if no such element is found otherwise an iterator from
 * the element */
list_t list_find(list_t list, const void * record); /* slow!! */

/* returns an item at a specified index in the list, the index better
 * be less than the size of the list */
void * list_index(list_t list, int index);   /* slow!! */

/* add the record to the end of the list if not already in it */
void list_add(list_t list, void * record);

/* removes a record from the list, the record better be in the list */
void list_remove(list_t list, const void * record); /* slow!! */

/* remove a random record from the list and return it */
void * list_remove_random(list_t list);

/* allocate a list and populate it with one element */
list_t list_alloc1(void * record);

/* allocate a list and populate it with two elements */
list_t list_alloc2(void * record1, void * record2);

/* allocate a list and populate it with three elements */
list_t list_alloc3(void * record1, void * record2, void * record3);

/* get 1 item from a list of size 1 */
void list_item1(void * list, void ** ppitem1);

/* get 2 items from a list of size 2 */
void list_item2(void * list, void ** ppitem1, void ** ppitem2);

/* get 3 items from a list of size 3 */
void list_item3(void * list, void ** ppitem1, void ** ppitem2,
                void  ** ppitem3);


#endif /* LIST_H */
